package lucene.server.web.task;

import lombok.extern.slf4j.Slf4j;
import lucene.server.common.datasource.PooledDataSource;
import lucene.server.common.enums.TaskEnum;
import lucene.server.common.model.TaskConfig;
import lucene.server.common.task.ITask;
import lucene.server.common.utils.DatabaseUtil;
import lucene.server.common.utils.DateUtils;
import lucene.server.common.utils.StringUtil;
import lucene.server.core.LuceneIndex;
import lucene.server.core.LuceneService;
import lucene.server.core.model.IndexConfig;
import lucene.server.core.util.DocumentUtil;
import lucene.server.web.config.LuceneConfig;
import lucene.server.web.dao.DynamicDataSource;
import lucene.server.web.dao.SystemDao;
import lucene.server.web.model.IndexJobLog;
import org.apache.lucene.document.Document;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;

/**
 * 其他任务
 *
 * **/
@Slf4j
public class SQLTask implements Runnable , ITask {

    private boolean isShutdown = false;
    private ScheduledFuture future;
    private boolean running = false;
    private TaskConfig taskConfig;
    private IndexConfig indexConfig;

    public SQLTask(TaskConfig taskConfig) {
        this.taskConfig = taskConfig;
        this.indexConfig = LuceneConfig.getIndexConfig(taskConfig.getIndexName());
    }
    public SQLTask(IndexConfig indexConfig) {
        this.indexConfig = indexConfig;
        taskConfig = new TaskConfig();
        taskConfig.setIndexName(indexConfig.getName());
        taskConfig.setType(TaskEnum.REBUILD);
        taskConfig.setName(indexConfig.getName()+"重建任务");
        taskConfig.setCron(indexConfig.getCron());
        taskConfig.setDbsql("select "+indexConfig.getFields() + " from "+indexConfig.getTable());
    }


    @Override
    public void run() {
        //这里刷新所有的
        if (running){
            log.info("当前任务正在运行：{}", this.indexConfig.getName() );
            return;
        }
        running = true;
        log.info("SQL任务开始，名称：{}", this.indexConfig.getName());
        IndexJobLog jobLog = new IndexJobLog(this.indexConfig.getName());
        PooledDataSource datasource = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try{
            datasource = DynamicDataSource.getDataSource(this.indexConfig.getConn());
            if(datasource == null){
                throw new RuntimeException("数据源忙，请扩大数据源配置或者稍后执行！");
            }
            statement = DatabaseUtil.getJobStatement(datasource.getConnection(),this.taskConfig.getDbsql());
            resultSet = statement.executeQuery();
            List<Document> documents = new ArrayList<>(10000);
            LuceneIndex basicService = LuceneService.getIndex(this.indexConfig.getName());
            if (basicService == null){
                throw new RuntimeException("索引不存在，请检查！");
            }
            if (TaskEnum.REBUILD.equals(this.taskConfig.getType())){
                basicService.getDeleteService().deleteAll();
            }
            int i = 0;
            while (resultSet.next() && !isShutdown) {
                documents.add(DocumentUtil.createDocument(resultSet, this.indexConfig.getFieldsConfig()));
                i++;
                if(i%10000==0){
                    if (TaskEnum.UPDATE.equals(this.taskConfig.getType())){
                        basicService.getUpdateService().updateDocuments(documents);
                    }else{
                        basicService.getInsertService().addDocuments(documents);
                    }
                    documents.clear();
                }
            }
            if (TaskEnum.UPDATE.equals(this.taskConfig.getType())){
                basicService.getUpdateService().updateDocuments(documents);
            }else{
                basicService.getInsertService().addDocuments(documents);
            }
            documents.clear();
            jobLog.setJobresult("任务完成，共"+i+"条数据");
            log.info("SQL任务结束，名称：{}，处理数据：{}条", this.indexConfig.getName(),i);
        }catch (Exception e){
            log.error("任务执行失败：{}",e);
            jobLog.setJobflag(false);
            jobLog.setJobresult("失败："+e.getMessage());
        }finally {
            running = false;
            DatabaseUtil.close(statement,resultSet);
        }
        try{
            jobLog.setEndtime(DateUtils.now());
            SystemDao.insertOrUpdate(jobLog);
            datasource.release();
        }catch (Exception e){ }
    }

    @Override
    public String getName() {
        return "sql_"+this.taskConfig.getName();
    }

    @Override
    public ScheduledFuture createScheduled(ThreadPoolTaskScheduler threadPoolTaskScheduler) {
        if (StringUtil.isNotEmpty(taskConfig.getCron())){
            this.future = threadPoolTaskScheduler.schedule(this, new CronTrigger(taskConfig.getCron()));
            return this.future;
        }else {
            //只能手动运行
            return null;
        }
    }

    @Override
    public String getTaskPlan() {
        if (StringUtil.isNotEmpty(taskConfig.getCron())){
            return taskConfig.getCron();
        }else {
            return "手动运行";
        }
    }

    @Override
    public void shutdown() {
        this.isShutdown = true;
        if (this.future != null) {
            this.future.cancel(true);
        }
    }
    @Override
    public boolean isRunning() {
        return running;
    }
}
